#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//下面都是本地文件
#include "head/default.h"         //define 宏定义及static变量                                      
#include "head/log.h"         //define 宏定义及static变量

void f_logging(enum LogLevel level, const char *fmt, ...);
int f_help(char program_name[]);
int f_get_log_file(char path[], char last_name[]);
int f_my_strncpy(char *string, int n);
int f_create_dir(char str[]);
int f_read_conf(char conf_file_path[], char *conf_name, char res_var[]);
int f_server(char *argv[], int daemon);
int f_client(int argc, char *argv[]);

char log_file_path[VAR_MAX_LEN] = "/var/log/msrt.log"; //默认日志路径

char *bl_default_comm[20] = {                             //定义命令黑名单, 高危操作不允许执行
                              "|xargs ",
                              "|rm ",
                              "|init ",
                              "|reboot ",
                              "|shutdown ",
                              "|halt ",
                              "|poweroff ",
                              " xargs ",
                              " rm ",
                              " init ",
                              " reboot ",
                              " shutdown ",
                              " halt ",
                              " poweroff ",
                              " -exec",
                              " -exec ",
                            };


int my_prepare(int argc, char *argv[]){

    if (argc < 2) {
        f_help(argv[0]);
        f_logging(WARN, "至少需要一个运行参数! 请根据上面的帮助信息使用!");
        printf("\n");
        return -1;
    } else if (strcmp(argv[1], "--help") == 0) {
        f_help(argv[0]);
        return -1;
    }

    if (argc % 2 == 0){
        f_logging(ERROR, "每个参数都必须指定一个varlue, 请检查!");
        return -1;
    }

    int opt_count = 11;
    char *opt[OPT_MAX_LEN] = {
        "role",     //第一个参数放role
        "host",     //第二个参数放host
        "port",     //第三个参数放port
        "comm",     //第四个参数放port
        "host-white",     //第五个参数white-list
        "host-black",     //第六个参数white-list
        "password",            //第七个参数white-list
        "log",                  //第八个参数white-list
        "conf",                 //第九个参数white-list
        "comm-black",      //第10个参数white-list
        "daemon"           //第11个参数daemon
    };

    //char *var_tmp[VAR_MAX_LEN];
    char *var[VAR_MAX_LEN]; //opt放参数, var放对应的值, 将参数做个默认排序
    for(int i = 0; i < ME_MAX_LEN - 1; i++) { //定义一个临时变量, 用来接收读取配置文件的字符串
        var[i] = (char *)malloc(VAR_MAX_LEN);
    }

    if (strlen(argv[0]) > ME_MAX_LEN) {
        printf("\n\n\n程序文件名称 : %s\n\n长度 : %zu\n\n超过最大长度 %d 限制!\n\n\n\n", argv[0], strlen(argv[0]), ME_MAX_LEN);
        return -1;
    }

    int pass_local = 0;
    int client_mark = 0; //判断client角色是否启用了-c
    for (int count = 1; count < argc; count += 2) {

        if (strlen(argv[count]) > VAR_TMP_MAX_LEN) {
            printf("\n\n\n参数 : %s\n\n长度是 : %zu\n\n超过最大长度 %d 限制!\n\n\n\n", argv[count], strlen(argv[count]), VAR_TMP_MAX_LEN);
            return -1;
        } else if (strlen(argv[count + 1]) > VAR_MAX_LEN) {
            printf("\n\n\n参数值 : %s\n\n长度是 : %zu\n\n超过最大长度 %d 限制!\n\n\n\n", argv[count + 1], strlen(argv[count + 1]), VAR_TMP_MAX_LEN);
            return -1;
        }

        if (strcmp(argv[count], "-r") == 0 || strcmp(argv[count], "--role") == 0) {
            var[0] = argv[count + 1];   //第一个参数值
        } else if (strcmp(argv[count], "-h") == 0 || strcmp(argv[count], "--host") == 0) {
            var[1] = argv[count + 1];
        } else if (strcmp(argv[count], "-p") == 0 || strcmp(argv[count], "--port") == 0) {
            var[2] = argv[count + 1];
        } else if (strcmp(argv[count], "-c") == 0 || strcmp(argv[count], "--comm") == 0) {
            var[3] = argv[count + 1];
            client_mark = 1;
        } else if (strcmp(argv[count], "-hw") == 0 || strcmp(argv[count], "--host-white") == 0) {
            var[4] = argv[count + 1];
        } else if (strcmp(argv[count], "-hb") == 0 || strcmp(argv[count], "--host-black") == 0) {
            var[5] = argv[count + 1];
        } else if (strcmp(argv[count], "--pass") == 0 || strcmp(argv[count], "--password") == 0) {
            memcpy(var[6], argv[count + 1], strlen(argv[count + 1]) + 1);
            //如果指定了密码, 就进行加密显示, 所以这里采用了直接copy内存的方式, 这样后面修改argv内存就不影响var了
            //var[6] = argv[count + 1];
            pass_local = count + 1;
        } else if (strcmp(argv[count], "--log") == 0) {
            var[7] = argv[count + 1];
            strcpy(log_file_path, var[7]);
        } else if (strcmp(argv[count], "--conf") == 0) {
            opt[8] = argv[count];  //第八个参数--conf 放配置文件
            var[8] = argv[count + 1];
        } else if (strcmp(argv[count], "-cb") == 0 || strcmp(argv[count], "--comm-black") == 0) {
            opt[9] = argv[count];  //第10个参数--comm-black 放命令黑名单
            var[9] = argv[count + 1];
        } else if (strcmp(argv[count], "-d") == 0 || strcmp(argv[count], "--daemon") == 0) {
            opt[10] = argv[count];  //第11个参数放守护进程
            var[10] = argv[count + 1];
        } else {
            char log_info[VAR_MAX_LEN];
            memset(log_info, 0x00, sizeof(log_info));
            sprintf(log_info, "%s%s%s", "不识别这个参数 ", argv[count], " 请使用 --help 查看帮助手册");
            f_logging(ERROR, log_info);
            return -1;
        }
    }

    //处理日志
    char log_file[VAR_MAX_LEN]; //定义日志目录, 日志文件名char数组
    f_get_log_file(log_file_path, log_file);          //返回日志路径中的文件名
    f_my_strncpy(log_file_path, (int)strlen(log_file_path) - (int)strlen(log_file)); //通过文件名取文件的路径
    f_create_dir(log_file_path);                               //日志目录是否存在, 不存在则创建
    sprintf(log_file_path, "%s%s", log_file_path, log_file);   //重新拼接
    
    //处理配置文件
    if (strlen(var[8]) != 0) {
        char res_var[VAR_MAX_LEN];
        for(int i = 0; i < opt_count; i++) {  //上面定义的参数个数
            //读取配置文件的配置, 将没有通过命令行指定的参数, 试着去读配置文件, 看看是否有配置
            if (strlen(var[i]) == 0) {
                f_read_conf(var[8], opt[i], res_var);
                f_my_strncpy(res_var, (int)strlen(res_var) - 1);
                memcpy(var[i], res_var, (strlen(res_var)) + 1);
            }
        }
    }

    if (strlen(var[6]) != 0) {
    //如果指定了密码, 就进行加密显示
        for (int l = 0; l < strlen(argv[pass_local]); l++) {
            argv[pass_local][l] = 'x';
        }
    } else {
        memcpy(var[6], PASS_INFO, strlen(PASS_INFO) + 1);
    }

    if (strlen(var[0]) == 0){
        f_logging(ERROR, "-r server|client 选项是必须的");
        return -1;
    }

    if (strlen(var[2]) == 0){
        memcpy(var[2], "9298", 5);
    }

    if (strcmp(var[10], "true") == 0 && strcmp(var[0], "server") == 0) { 
        //如果启用了守护进程选项, 且role是server, 则判断端口是否被占用, 如果未被占用则继续向下执行, 如果端口被占用则退出本次监测
        if (f_server(var, 1) != 0) {
            return -1;
        }
    }
    char log_info[VAR_MAX_LEN];
    if (strlen(var[7]) != 0){
        strcpy(log_file_path, var[7]);
        memset(log_info, 0x00, sizeof(log_info));
        sprintf(log_info, "SERVER --> LOG_FILE : %s", log_file_path);
        f_logging(WARN, log_info);
    }

    sprintf(log_info, "Version : %.1f", VERSION);
    if (client_mark == 0 && strcmp(var[10], "true") != 0) {   //使用了-c
        f_logging(WARN, log_info);
    }
    int res_state = -1;
    if (strcmp(var[0], "server") == 0) { //strcmp(var[0], "server"), 判断第一个参数的值是否等于server, 返回0表示相等
        res_state = f_server(var, 0);                   //server
    } else if (strcmp(var[0], "client") == 0) {
        while (1) {
            res_state = f_client(argc / 2, var);        // client
            if (client_mark == 1) {   //使用了-c
                break;
            }
        }
    }

    return res_state;
}

int main(int argc, char *argv[]) {

    return my_prepare(argc, argv);
}
